home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1993, 1994 Marc Parmet.
- * This file is part of the Macintosh port of GNU Emacs.
- *
- * GNU Emacs is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
- #if defined(THINK_C)
- #include <MacHeaders>
- #else
- #include <Types.h>
- #include <Memory.h>
- #include <Quickdraw.h>
- #include <Windows.h>
- #include <Errors.h>
- #endif
-
- #include <AppleEvents.h>
- #include <AERegistry.h>
- #include <Aliases.h>
- #include <Script.h>
- #include <Folders.h>
- #include "sys/unistd.h"
- #include "sys/file.h"
- #include "sys/stat.h"
- #include "errno.h"
- #include "utime.h"
-
- static int
- rename_specs(FSSpec *old_spec,FSSpec *new_spec)
- {
- short err;
- FSSpec temp_spec;
- static unsigned char tempname[] = "\p##temp##";
-
- if (old_spec->vRefNum != new_spec->vRefNum) return diffVolErr;
- if (old_spec->parID == new_spec->parID) {
- err = FSpRename(old_spec,new_spec->name);
- return err;
- }
- else {
- err = FSpRename(old_spec,tempname);
- if (err) return err;
- err = FSMakeFSSpec(old_spec->vRefNum,old_spec->parID,tempname,&temp_spec);
- if (err) return err;
- err = CatMove(temp_spec.vRefNum,temp_spec.parID,temp_spec.name,new_spec->parID,(ConstStr255Param)"\p");
- if (err) return err;
- err = FSMakeFSSpec(new_spec->vRefNum,new_spec->parID,tempname,&temp_spec);
- if (err) return err;
- err = FSpRename(&temp_spec,new_spec->name);
- return err;
- }
- }
-
- int
- symlink_internal(char *target,char *linkname)
- {
- unsigned char s[256];
- CInfoPBRec pb;
- long desk_dirID;
- int retcode = -1;
- AEDesc targetAppl;
- short err,desk_vRefNum;
- AppleEvent event,reply;
- AEDescList selectionList;
- extern pascal short ae_send_idle_function();
- static AEIdleUPP ae_send_idle_function_upp;
- AliasHandle target_alias = 0L,target_parent_alias = 0L;
- int have_targetAppl = 0,have_event = 0,have_selectionList = 0;
- FSSpec target_spec,linkname_spec,target_parent_spec,alias_spec;
-
- if (ae_send_idle_function_upp == 0L)
- ae_send_idle_function_upp = NewAEIdleProc(ae_send_idle_function);
-
- err = unixfn2FSSpec_internal(target,&target_spec,0);
- if (err) goto error;
- if (target_spec.parID == fsRtParID)
- target_parent_spec = target_spec;
- else {
- pb.dirInfo.ioNamePtr = s;
- pb.dirInfo.ioFDirIndex = -1;
- pb.dirInfo.ioVRefNum = target_spec.vRefNum;
- pb.dirInfo.ioDrDirID = target_spec.parID;
- err = PBGetCatInfo(&pb,0);
- if (err) goto error;
- err = FSMakeFSSpec(target_spec.vRefNum,pb.dirInfo.ioDrParID,s,&target_parent_spec);
- if (err) goto error;
- }
- err = unixfn2FSSpec_internal(linkname,&linkname_spec,0);
- if (err && err != fnfErr) goto error;
- if (err == noErr) { set_errno(EEXIST); return -1; }
-
- // Create the alias.
- err = NewAlias(0L,&target_parent_spec,&target_parent_alias);
- if (err) goto error;
- err = NewAliasMinimal(&target_spec,&target_alias);
- if (err) goto error;
-
- err = AECreateDesc(typeApplSignature,"MACS",sizeof(long),&targetAppl);
- if (err) goto error;
- have_targetAppl = 1;
- err = AECreateAppleEvent(kAEFinderEvents,kAEAliasSelection,&targetAppl,
- kAutoGenerateReturnID,kAnyTransactionID,&event);
- if (err) goto error;
- have_event = 1;
- HLock((Handle)target_parent_alias);
- err = AEPutParamPtr(&event,keyDirectObject,typeAlias,*target_parent_alias,
- (**target_parent_alias).aliasSize);
- if (err) goto error;
- err = AECreateList(0,0,0,&selectionList);
- if (err) goto error;
- have_selectionList = 1;
- HLock((Handle)target_alias);
- err = AEPutPtr(&selectionList,0,typeAlias,*target_alias,(**target_alias).aliasSize);
- if (err) goto error;
- err = AEPutParamDesc(&event,keySelection,&selectionList);
- if (err) goto error;
- err = AESend(&event,&reply,kAENeverInteract | kAEWaitReply,kAENormalPriority,
- kAEDefaultTimeout,ae_send_idle_function_upp,0L);
- if (err) goto error;
-
- // Have the alias, now move it and rename it.
- // We have to guess where the new alias is and what it's called.
- if (target_spec.parID == fsRtParID) {
- err = FindFolder(target_spec.vRefNum,'desk',0,&desk_vRefNum,&desk_dirID);
- if (err) goto error;
- pstrcpy(s,target_spec.name);
- pstrcat(s,"\p alias");
- err = FSMakeFSSpec(desk_vRefNum,desk_dirID,s,&alias_spec);
- if (err) goto error;
- }
- else {
- pstrcpy(s,target_spec.name);
- pstrcat(s,"\p alias");
- err = FSMakeFSSpec(target_spec.vRefNum,target_spec.parID,s,&alias_spec);
- if (err) goto error;
- }
-
- err = rename_specs(&alias_spec,&linkname_spec);
- if (err) goto error;
-
- retcode = 0;
-
- error:
- if (target_alias != 0L) DisposHandle((Handle)target_alias);
- if (target_parent_alias != 0L) DisposHandle((Handle)target_parent_alias);
- if (have_targetAppl) AEDisposeDesc(&targetAppl);
- if (have_event) AEDisposeDesc(&event);
- if (have_selectionList) AEDisposeDesc(&selectionList);
- set_errno(err);
- return retcode;
- }
-
- int
- access_internal(char *filename,int mode)
- {
- struct stat st;
- int err,check_lock;
-
- switch (mode) {
- case F_OK:
- case R_OK:
- case X_OK:
- check_lock = 0;
- break;
- case W_OK:
- check_lock = 1;
- break;
- default:
- set_errno(EINVAL);
- return -1;
- }
-
- err = stat_internal(filename,&st,0);
- if (err) return err;
- if (!check_lock) return 0;
- if (st.st_mode & 0200) return 0;
- set_errno(EACCES);
- return -1;
- }
-
- int
- unlink_internal(char *s)
- {
- short err;
- FSSpec spec;
-
- // This works for files and empty folders, and fortunately fails for volumes.
- err = unixfn2FSSpec_internal(s,&spec,1);
- if (err) { set_errno(err); return -1; }
- err = FSpDelete(&spec);
- if (err) { set_errno(err); return -1; }
- return 0;
- }
-
- int
- rename_internal(char *old,char *new)
- {
- short err;
- FSSpec old_spec,new_spec;
-
- err = unixfn2FSSpec_internal(old,&old_spec,1);
- if (err) { set_errno(err); return -1; }
- err = unixfn2FSSpec_internal(new,&new_spec,0);
- if (err && err != fnfErr) { set_errno(err); return -1; }
- err = rename_specs(&old_spec,&new_spec);
- if (err) { set_errno(err); return -1; }
- return 0;
- }
-
- int
- readlink_internal(char *linkname,char *target,int n)
- {
- int err,len;
- FSSpec spec;
- static Handle s;
- Boolean isFolder,wasAliased;
-
- if (s) { DisposHandle(s); s = 0L; }
-
- // If the filename is not a link, return -1.
- err = unixfn2FSSpec_internal(linkname,&spec,1);
- if (err) { set_errno(err); return -1; }
- err = ResolveAliasFile(&spec,0,&isFolder,&wasAliased);
- if (err) { set_errno(err); return -1; }
- if (!wasAliased) { set_errno(EUNDOC); return -1; }
-
- err = unixfn2FSSpec_internal(linkname,&spec,0);
- if (err) { set_errno(err); return -1; }
- err = FSSpec2unixfn_internal(&spec,&s);
- if (err) { set_errno(err); return -1; }
- HLock(s);
- len = strlen(*s);
- if (len >= n) {
- memcpy(target,*s,n-1);
- target[n-1] = '\0';
- }
- else {
- memcpy(target,*s,len);
- target[len] = '\0';
- }
- HUnlock(s);
- return strlen(target);
- }
-
- int
- mkdir_internal(char *name,int mode)
- {
- short err;
- FSSpec spec;
- long newDirID;
-
- err = unixfn2FSSpec_internal(name,&spec,0);
- if (err == noErr) { set_errno(EEXIST); return -1; }
- if (err != fnfErr) { set_errno(err); return -1; }
-
- err = FSpDirCreate(&spec,smSystemScript,&newDirID);
- if (err) { set_errno(err); return -1; }
- return 0;
- }
-
- int
- rmdir_internal(char *name)
- {
- short err;
- FSSpec spec;
- CInfoPBRec pb;
-
- err = unixfn2FSSpec_internal(name,&spec,0);
- if (err) { set_errno(err); return -1; }
-
- // Make sure it's a directory.
- pb.dirInfo.ioFDirIndex = 0;
- pb.dirInfo.ioNamePtr = spec.name;
- pb.dirInfo.ioVRefNum = spec.vRefNum;
- pb.dirInfo.ioDrDirID = spec.parID;
- err = PBGetCatInfo(&pb,0);
- if (err) { set_errno(err); return -1; }
- if (!(pb.dirInfo.ioFlAttrib & 0x10)) { set_errno(ENOTDIR); return -1; }
-
- err = FSpDelete(&spec);
- if (err == fBsyErr) { set_errno(EDIRNE); return -1; }
- if (err) { set_errno(err); return -1; }
- return 0;
- }
-
- int
- utime_internal(char *name,struct utimbuf *time)
- {
- short err;
- FSSpec spec;
- CInfoPBRec pb;
- unsigned long modtime;
- long actime;
-
- if (time != 0L) {
- modtime = time->modtime;
- actime = time->actime;
- }
- else {
- GetDateTime(&modtime);
- actime = modtime;
- }
-
- err = unixfn2FSSpec_internal(name,&spec,1);
- if (err) { set_errno(err); return -1; }
-
- pb.dirInfo.ioVRefNum = spec.vRefNum;
- pb.dirInfo.ioDrDirID = spec.parID;
- pb.dirInfo.ioNamePtr = spec.name;
- pb.dirInfo.ioFDirIndex = 0;
- err = PBGetCatInfo(&pb,0);
- if (err) { set_errno(err); return -1; }
-
- pb.dirInfo.ioDrDirID = spec.parID;
- if (modtime != 0) pb.dirInfo.ioDrMdDat = modtime;
- if (actime != 0) pb.dirInfo.ioDrCrDat = actime;
- err = PBSetCatInfo(&pb,0);
- if (err) { set_errno(err); return -1; }
-
- return 0;
- }
-
- int
- chmod_internal(char *filename,int mode)
- {
- short err;
- FSSpec spec;
-
- err = unixfn2FSSpec_internal(filename,&spec,0);
- if (err) { set_errno(err); return -1; }
- if (mode & 0200)
- err = FSpRstFLock(&spec);
- else
- err = FSpSetFLock(&spec);
- if (err) { set_errno(err); return -1; }
- return 0;
- }
-
- int
- chown_internal(char *filename,int own)
- {
- short err;
- FSSpec spec;
- FInfo info;
-
- err = unixfn2FSSpec_internal(filename,&spec,0);
- if (err) { set_errno(err); return -1; }
- err = FSpGetFInfo(&spec,&info);
- if (err) { set_errno(err); return -1; }
- info.fdCreator = own;
- err = FSpSetFInfo(&spec,&info);
- if (err) { set_errno(err); return -1; }
- return 0;
- }
-
- int
- chgrp_internal(char *filename,int grp)
- {
- short err;
- FSSpec spec;
- FInfo info;
-
- err = unixfn2FSSpec_internal(filename,&spec,0);
- if (err) { set_errno(err); return -1; }
- err = FSpGetFInfo(&spec,&info);
- if (err) { set_errno(err); return -1; }
- info.fdType = grp;
- err = FSpSetFInfo(&spec,&info);
- if (err) { set_errno(err); return -1; }
- return 0;
- }
-